const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const path = require('path');
const wrtc = require('wrtc');
const fs = require('fs');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

// 设置静态文件服务
app.use(express.static(path.join(__dirname, '../client')));
app.use('/card', express.static(path.join(__dirname, '../client/card')));

// 添加根路由
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../client/wgzz.html'));
});

// 包含所有房间的信息，每个房间有唯一的ID
let rooms = {};

// WebRTC连接管理
let rtcPeers = {};
let videoReadyClients = new Set();

// 反向代理 /api 到 http://localhost:5000
app.use('/api', createProxyMiddleware({
    target: 'http://localhost:5000',
    changeOrigin: true,
    ws: true
}));

// 当客户端连接时
wss.on('connection', (ws) => {
    console.log('Client connected');
    
    // 接收客户端消息
    ws.on('message', async (message) => {
        const data = JSON.parse(message);
        console.log('[服务器] 收到消息:', JSON.stringify(data, null, 2));
        
        // 处理加入房间的消息
        if (data.type === 'joinRoom') {
            handleJoinRoom(ws, data);
        }
        // 处理游戏操作的消息
        else if (data.type === 'gameAction') {
            handleGameAction(ws, data);
        }
        // 处理游戏状态同步
        else if (data.type === 'syncGameState') {
            handleGameStateSync(ws, data);
        }
        // 处理卖出卡牌（删除手牌/战场卡牌）
        else if (data.type === 'sellCard') {
            handleSellCard(ws, data);
        }
        if (data.type === 'rtc-offer') {
            console.log('[服务器] 收到 rtc-offer，准备建立 WebRTC 连接');
            try {
                // 客户端发来offer，服务器回应answer
                const peer = new wrtc.RTCPeerConnection({
                    iceServers: [
                        { urls: 'stun:stun.l.google.com:19302' },
                        {
                            urls: 'turn:openrelay.metered.ca:80',
                            username: 'openrelayproject',
                            credential: 'openrelayproject'
                        }
                    ]
                });
                rtcPeers[ws] = peer;
                
                peer.onicecandidate = (event) => {
                    console.log('[服务器] ICE 候选者:', event.candidate ? '有候选者' : '无候选者');
                };
                
                peer.oniceconnectionstatechange = () => {
                    console.log('[服务器] ICE 连接状态变更:', peer.iceConnectionState);
                };
                
                peer.onconnectionstatechange = () => {
                    console.log('[服务器] 连接状态变更:', peer.connectionState);
                };
                
                peer.onerror = (error) => {
                    console.error('[服务器] WebRTC 错误:', error);
                };
                
                peer.ondatachannel = (event) => {
                    console.log('[服务器] 数据通道已建立');
                    const channel = event.channel;
                    channel.onopen = async () => {
                        console.log('[服务器] 数据通道已打开，准备发送视频');
                        try {
                            // 读取mp4并分片发送
                            const videoPath = path.join(__dirname, 'source', 'fight.mp4');
                            console.log('[服务器] 读取视频文件:', videoPath);
                            const videoBuffer = await fs.promises.readFile(videoPath);
                            console.log('[服务器] 视频文件大小:', videoBuffer.length, '字节');
                            
                            // 确保数据通道已准备好
                            if (channel.readyState !== 'open') {
                                console.error('[服务器] 数据通道未打开，当前状态:', channel.readyState);
                                return;
                            }
                            
                            const chunkSize = 64 * 1024;  // 64KB chunks
                            let chunkCount = 0;
                            let totalSent = 0;
                            
                            for (let i = 0; i < videoBuffer.length; i += chunkSize) {
                                const chunk = videoBuffer.slice(i, i + chunkSize);
                                try {
                                    channel.send(chunk);
                                    chunkCount++;
                                    totalSent += chunk.length;
                                    if (chunkCount % 10 === 0) {
                                        console.log(`[服务器] 已发送 ${chunkCount} 个数据块，共 ${totalSent} 字节`);
                                    }
                                } catch (error) {
                                    console.error('[服务器] 发送数据块时出错:', error);
                                    break;
                                }
                            }
                            
                            console.log('[服务器] 视频发送完成，发送结束标记');
                            console.log(`[服务器] 总共发送 ${chunkCount} 个数据块，共 ${totalSent} 字节`);
                            channel.send('END_OF_VIDEO');
                        } catch (error) {
                            console.error('[服务器] 发送视频时出错:', error);
                        }
                    };
                    
                    channel.onerror = (error) => {
                        console.error('[服务器] 数据通道错误:', error);
                    };
                    
                    channel.onclose = () => {
                        console.log('[服务器] 数据通道已关闭');
                    };
                    
                    channel.onbufferedamountlow = () => {
                        console.log('[服务器] 数据通道缓冲区已清空');
                    };
                };
                
                await peer.setRemoteDescription(new wrtc.RTCSessionDescription(data.offer));
                console.log('[服务器] 已设置远程描述');
                const answer = await peer.createAnswer();
                console.log('[服务器] 已创建应答');
                await peer.setLocalDescription(answer);
                console.log('[服务器] 已设置本地描述，发送应答');
                ws.send(JSON.stringify({ type: 'rtc-answer', answer: peer.localDescription }));
            } catch (error) {
                console.error('[服务器] 处理 WebRTC offer 时出错:', error);
            }
        } else if (data.type === 'video-played') {
            videoReadyClients.add(ws);
            if (videoReadyClients.size === getRoomPlayerCount()) {
                startNewRoundForAll();
                videoReadyClients.clear();
            }
        } else if (data.type === 'endRound') {
            console.log('[服务器] 收到 endRound 消息，准备发送 play-video');
            // 找到该玩家所在房间
            let foundRoom = null;
            for (const roomId in rooms) {
                const room = rooms[roomId];
                if ((room.player1 && room.player1.ws === ws) || (room.player2 && room.player2.ws === ws)) {
                    foundRoom = room;
                    break;
                }
            }
            if (foundRoom) {
                if (foundRoom.player1 && foundRoom.player1.ws) {
                    foundRoom.player1.ws.send(JSON.stringify({ type: 'play-video', video: 'xxx' }));
                }
                if (foundRoom.player2 && foundRoom.player2.ws) {
                    foundRoom.player2.ws.send(JSON.stringify({ type: 'play-video', video: 'xxx' }));
                }
            }
        }
    });
    
    // 当客户端断开连接时
    ws.on('close', () => {
        console.log('Client disconnected');
        
        // 查找并清理此客户端所在的房间
        for (const roomId in rooms) {
            const room = rooms[roomId];
            if (room.player1 === ws || room.player2 === ws) {
                // 如果两个玩家都断开了连接，删除房间
                if (!room.player1 || !room.player2) {
                    console.log(`Room ${roomId} closed`);
                    delete rooms[roomId];
                } else {
                    // 否则，只移除断开的玩家
                    if (room.player1 === ws) {
                        room.player1 = null;
                        if (room.player2) {
                            room.player2.ws.send(JSON.stringify({
                                type: 'opponentDisconnected',
                                message: '对手已断开连接'
                            }));
                        }
                    }
                    if (room.player2 === ws) {
                        room.player2 = null;
                        if (room.player1) {
                            room.player1.ws.send(JSON.stringify({
                                type: 'opponentDisconnected',
                                message: '对手已断开连接'
                            }));
                        }
                    }
                }
                break;
            }
        }
    });
});

// 处理加入房间的请求
function handleJoinRoom(ws, data) {
    const { roomId, playerName } = data;
    
    // 如果房间不存在，创建新房间
    if (!rooms[roomId]) {
        rooms[roomId] = {
            id: roomId,
            player1: null,
            player2: null,
            status: 'waiting', // waiting, playing, ended
            // 初始化全局游戏状态
            gameState: {
                round: 1,
                timer: 20,
                isRoundEnd: false
            },
            player1State: null,
            player2State: null
        };
    }
    
    const room = rooms[roomId];
    
    // 将玩家加入房间
    if (!room.player1) {
        room.player1 = { ws, name: playerName };
        // 初始化player1的游戏状态
        room.player1State = {
            level: 1,
            gold: 100,
            hand: [],
            battle: [],
            maxHandSize: 6,
            health: 30,
            availableCards: new Array(6).fill(0)
        };
        ws.send(JSON.stringify({
            type: 'roomUpdate',
            status: 'waiting',
            role: 'player1',
            message: `等待玩家2加入房间${roomId}...`
        }));
    } else if (!room.player2) {
        room.player2 = { ws, name: playerName };
        // 初始化player2的游戏状态
        room.player2State = {
            level: 1,
            gold: 100,
            hand: [],
            battle: [],
            maxHandSize: 6,
            health: 30,
            availableCards: new Array(6).fill(0)
        };
        room.status = 'playing';
        
        // 通知两个玩家游戏开始
        const initialGameState = {
             player: room.player1State,
             opponent: room.player2State,
             round: room.gameState.round,
             timer: room.gameState.timer,
             isRoundEnd: room.gameState.isRoundEnd
        };
        room.player1.ws.send(JSON.stringify({
            type: 'roomUpdate',
            status: 'playing',
            role: 'player1',
            message: '玩家2已加入，游戏开始！',
            gameState: initialGameState
        }));
        const initialGameStateSwapped = {
             player: room.player2State,
             opponent: room.player1State,
             round: room.gameState.round,
             timer: room.gameState.timer,
             isRoundEnd: room.gameState.isRoundEnd
        };
        room.player2.ws.send(JSON.stringify({
            type: 'roomUpdate',
            status: 'playing',
            role: 'player2',
            message: '已加入房间，游戏开始！',
             gameState: initialGameStateSwapped
        }));
    } else {
        // 房间已满
        ws.send(JSON.stringify({
            type: 'error',
            message: '房间已满，请选择其他房间或创建新房间'
        }));
        ws.terminate();
    }
}

// 处理游戏操作
function handleGameAction(ws, data) {
    const { roomId, action, gameState } = data;
    
    const room = rooms[roomId];
    if (!room || room.status !== 'playing') {
        return;
    }
    
    // 更新房间的游戏状态
    room.gameState = gameState;
    
    // 将游戏状态同步给对手
    const opponent = room.player1.ws === ws ? room.player2 : room.player1;
    if (opponent) {
        opponent.ws.send(JSON.stringify({
            type: 'gameStateUpdate',
            gameState: gameState,
            action: action
        }));
    }
}

// 处理游戏状态同步
function handleGameStateSync(ws, data) {
    const { roomId, gameState } = data;
    const room = rooms[roomId];
    if (!room || room.status !== 'playing') return;

    let isPlayer1 = room.player1 && room.player1.ws === ws;
    if (isPlayer1) {
        room.player1State = gameState.player;
    } else {
        room.player2State = gameState.player;
    }

    // 更新全局状态
    room.gameState.timer = gameState.timer;
    room.gameState.round = gameState.round;
    room.gameState.isRoundEnd = gameState.isRoundEnd;

    // 组装对手视角
    let opponent, stateForOpponent;
    if (isPlayer1) {
        opponent = room.player2;
        stateForOpponent = {
            player: room.player2State,
            opponent: room.player1State,
            round: room.gameState.round,
            timer: room.gameState.timer,
            isRoundEnd: room.gameState.isRoundEnd
        };
    } else {
        opponent = room.player1;
        stateForOpponent = {
            player: room.player1State,
            opponent: room.player2State,
            round: room.gameState.round,
            timer: room.gameState.timer,
            isRoundEnd: room.gameState.isRoundEnd
        };
    }
    if (opponent && opponent.ws) {
        opponent.ws.send(JSON.stringify({
            type: 'gameStateUpdate',
            gameState: stateForOpponent
        }));
    }
}

// 处理卖出卡牌（删除手牌/战场卡牌）
function handleSellCard(ws, data) {
    const { roomId, cardId, area, isMerged } = data;
    const room = rooms[roomId];
    if (!room || room.status !== 'playing') return;

    let isPlayer1 = room.player1 && room.player1.ws === ws;
    let playerState = isPlayer1 ? room.player1State : room.player2State;

    // 支持对象型卡牌删除
    if (area === 'hand') {
        const idx = playerState.hand.findIndex(c => (typeof c === 'object' ? c.id : c) === Number(cardId));
        if (idx !== -1) playerState.hand.splice(idx, 1);
    } else if (area === 'battle') {
        const idx = playerState.battle.findIndex(c => (typeof c === 'object' ? c.id : c) === Number(cardId));
        if (idx !== -1) playerState.battle.splice(idx, 1);
    }
    playerState.gold = parseInt(playerState.gold) + 1;

    // 同步给双方
    let stateForPlayer = {
        player: playerState,
        opponent: isPlayer1 ? room.player2State : room.player1State,
        round: room.gameState.round,
        timer: room.gameState.timer,
        isRoundEnd: room.gameState.isRoundEnd
    };
    ws.send(JSON.stringify({
        type: 'gameStateUpdate',
        gameState: stateForPlayer
    }));

    let opponent = isPlayer1 ? room.player2 : room.player1;
    if (opponent && opponent.ws) {
        let stateForOpponent = {
            player: isPlayer1 ? room.player2State : room.player1State,
            opponent: playerState,
            round: room.gameState.round,
            timer: room.gameState.timer,
            isRoundEnd: room.gameState.isRoundEnd
        };
        opponent.ws.send(JSON.stringify({
            type: 'gameStateUpdate',
            gameState: stateForOpponent
        }));
    }
}

function handleCountdownEnd(ws, data) {
    const { roomId } = data;
    console.log('[服务器] handleCountdownEnd 被调用，roomId:', roomId);
    const room = rooms[roomId];
    if (room && room.status === 'playing') {
        console.log('[服务器] 计时器结束，准备发送 play-video 消息');
        if (room.player1 && room.player1.ws) {
            console.log('[服务器] 向 player1 发送 play-video');
            room.player1.ws.send(JSON.stringify({ type: 'play-video' }));
        }
        if (room.player2 && room.player2.ws) {
            console.log('[服务器] 向 player2 发送 play-video');
            room.player2.ws.send(JSON.stringify({ type: 'play-video' }));
        }
    }
}

function getRoomPlayerCount() {
    // 假设只有一个房间，返回2
    return 2;
}

function startNewRoundForAll() {
    for (const roomId in rooms) {
        const room = rooms[roomId];
        if (room.player1 && room.player1.ws) {
            room.player1.ws.send(JSON.stringify({ type: 'startNewRound' }));
        }
        if (room.player2 && room.player2.ws) {
            room.player2.ws.send(JSON.stringify({ type: 'startNewRound' }));
        }
    }
}

// 启动服务器
const PORT = process.env.PORT || 3000;
server.listen(PORT, '0.0.0.0', () => {
    console.log(`Server is running on port ${PORT}`);
});